package com.erlang.spring.test;

import com.erlang.spring.pojo.HouseOwner;
import com.erlang.spring.pojo.HouseProxy;
import com.erlang.spring.proxy.HouseProxyStatic;
import com.erlang.spring.service.HouseAgencyCompany;
import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Description：租客
 */
public class Customer {

    //被代理对象
    private HouseOwner houseOwner = new HouseOwner();

    @Test
    public void needHouseStatic(){
        houseOwner.rentingHouse();
        System.out.println("==================================");
        HouseAgencyCompany houseAgencyCompany = new HouseProxyStatic();
        houseAgencyCompany.rentingHouse();
    }

    @Test
    public void needHouseDyJDK(){

        /**
         * //方法1: 该方法用于获取指定动态代理对象所关联的调用处理器
         * static InvocationHandler getInvocationHandler(Object proxy)
         *
         * //方法2：该方法用于获取关联于指定类装载器和一组接口的动态代理对象
         * static Class getProxyClass(ClassLoader loader, Class[] interfaces)
         *
         * //方法3：该方法用于判断指定类对象是否是一个动态代理类
         * static boolean isProxyClass(Class cl)
         *
         * //方法4：该方法用于为指定类装载器、一组接口及调用处理器生成动态代理对象：1、类加载器 2、接口数组、调用处理器（增强部分的业务代码）
         * static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
         */

        HouseAgencyCompany proxy= (HouseAgencyCompany) Proxy.newProxyInstance(
            // (当前类的字节码对象,当前类的接口,增强方法)
            houseOwner.getClass().getClassLoader(),
            houseOwner.getClass().getInterfaces(),
            //方法1: 该方法用于获取指定动态代理对象所关联的调用处理器
            /**
             *该方法负责集中处理动态代理类上的所有方法调用。
             *  第一个参数是代理对象，
             *  第二个参数是被调用的方法对象，
             *  第三个方法是调用参数。
             *  调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行。 Object invoke(Object proxy, Method method, Object[] args)
             */
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    String name = method.getName();
                    if ("rentingHouse".equals(name)) {
                        //前置增强
                        System.out.println("我给你指派一个我们的员工，带你去看房子");
                        System.out.println("介绍房屋情况");
                    }
                    Object result = method.invoke(houseOwner, args);
                    // 1.返回执行结果 2.将执行权交个方法的调用者
                    return result;
                }
            });
        proxy.rentingHouse();
    }

    @Test
    public void needHouseProxyCglib(){
        /**
         * Enhancer类是CGLib中的一个字节码增强器，作用用于生成代理对象
         *
         *  //方法1：该方法用于为指定目标类、回调对象 1、类的类型，2、调用处理器
         *  public static Object create(Class type, Callback callback)
         */
        HouseProxy houseProxy = (HouseProxy) Enhancer.create(HouseProxy.class, new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("中介小王：带你看房子");
                Object invoke = method.invoke(houseOwner, objects);
                System.out.println("中介小王:下次有朋友要租房子帮我介绍一下");
                return invoke;
            }
        });
        houseProxy.rentingHouse();
    }
}